/***************************************************************************
 *   Copyright (C) 2011  by TinySofts                                      *
 *   tinysofts@gmail.com                                                   *
 *   All Rights Reserved.                                                  *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   Refer to http://code.google.com/p/tinydict/                           *
 ***************************************************************************/

/*
    StarDict Class
    Status:Open;ReleaseReady;M
*/

#include "tdict.h"

unsigned int _toInt2(char *str)
{
    unsigned int i=0;
    unsigned char ch = 0;
    ch = str[0];
    i|=ch;
    i<<=8;
    ch = str[1];
    i|=ch;
    i<<=8;
    ch = str[2];
    i|=ch;
    i<<=8;
    ch = str[3];
    i|=ch;
    return i;
}

TDict::TDict()
{
    dz = NULL;
    state = false;
    wordNum = 0;
    _type = DICTTYPE_STARDICT;
}

QString TDict::findWord(int s, int& offset, int& size)
{
    offset=-1;
    size=-1;
    /*just in case*/
    if(!state)
    {
        return "";
    }
    int beg = wordlist[s];
    int end = wordlist[s+1];
    //QByteArray r((char*)mapped+beg,end-beg-1);
    char tmp[256+1+8];
    idx.seek(beg);
    idx.read(tmp,end-beg);
    QString r(tmp);
    offset = _toInt2(tmp+end-beg-8);
    size = _toInt2(tmp+end-beg-4);
    return r.toLower();
}

QString TDict::getWord(int s, int& offset, int& size)
{
    offset=-1;
    size=-1;
    /*just in case*/
    if(!state)
    {
        return "";
    }
    int beg = wordlist[s];
    int end = wordlist[s+1];
    //QByteArray r((char*)mapped+beg,end-beg-1);
    char tmp[256+1+8];
    memset(tmp,0,sizeof(tmp));
    idx.seek(beg);
    idx.read(tmp,end-beg);
    QString r(tmp);
    offset = _toInt2(tmp+end-beg-8);
    size = _toInt2(tmp+end-beg-4);
    return r;
}

QByteArray TDict::readDict(int offset, int size)
{
    /*just in case*/
    if(!state)
    {
        return "";
    }
    dz->seek(offset);
    return dz->read(size);
}

QByteArray TDict::lookUpDict(const QString & word)
{
    if(!state)
    {
        return "";
    }
    /*find the word*/
    QString w = word.trimmed().toLower();
    int beg = 0;
    int end = wordNum-1;
    int offset = 0;
    int size = 0;
    while(beg<=end)
    {
        //*
        int mid=(beg+end)/2;
        QString r=findWord(mid,offset,size);
        if(r==w) {
            return readDict(offset,size);
        }
        if(w>r) {
            beg = mid+1;
        }
        else {
            end = mid-1;
        }
        //*/
    }
    return "";
}

QByteArray TDict::lookUpDict2(const QString & word)
{
    if(!state)
    {
        return "";
    }
    QByteArray interpretion("");
    /*find the word*/
    QString w = word.trimmed().toLower();
    int beg = 0;
    int end = wordNum-1;
    int offset = 0;
    int size = 0;
    QString r;
    while(beg<=end)
    {
        //*
        int mid=(beg+end)/2;
        r=findWord(mid,offset,size);
        if(r==w) {
            interpretion.append(w+"\r\n");
            interpretion.append(readDict(offset,size));
            return interpretion;
        }
        if(w>r) {
            beg = mid+1;
        }
        else {
            end = mid-1;
        }
        //*/
    }
    /*return the word near enough*/
    interpretion.append(r+"\r\n");
    interpretion.append(readDict(offset,size));
    return interpretion;
}

bool TDict::initDictDB(QString path, QString name)
{
    return setPath(path,name);
}

bool TDict::setPath(QString path, QString name)
{
    /**/
    QString idxpath = path+QDir::separator()+name+".idx";
    idx.setFileName(idxpath);
    if(!idx.exists())
    {
        return false;
    }

    QString dzpath = path+QDir::separator()+name+".dict.dz";
    QFile tmp(dzpath);
    if(!tmp.exists())
    {
        return false;
    }
    dz = new DictZip(dzpath);

    /**/
    idx.open(QFile::ReadOnly);
    //mapped = idx.map(0,idx.size());
    int i = 0;
    int runner = 0;
    wordlist.append(runner);
    QByteArray inx = idx.readAll();
    while(true)
    {
        runner = inx.indexOf('\0',runner);
        if(runner == -1)
            break;
        runner+=9;
        wordlist.append(runner);
        i+=1;
        wordNum++;
    }
    state = true;
    return true;
}

bool TDict::reset()
{
    return true;
}

bool TDict::init()
{
   return state;
}
